#include <iostream>
#include <string>
#include <vector>
#include <filesystem>
#include <algorithm>

#include "stream/ClassRead.h"
#include "oop/InstanceKlass.h"
#include "classfile/BootClassLoader.h"
#include "runtime/JavaThread.h"
#include "native/JavaNativeInterface.h"
#include "interpreter/CodeRunBase.h"
#include "interpreter/CodeRunNative.h"
#include "runtime/Threads.h"

using namespace std;

void startVM();
bool parseArgs(int argc, char *argv[],
               std::vector<std::filesystem::path> &classpaths,
               std::string &mainClassName);
std::string joinClasspath(const std::vector<std::filesystem::path> &classpaths);

int main(int argc, char *argv[])
{
  std::vector<std::filesystem::path> classpaths;
  std::string mainClass;

  if (!parseArgs(argc, argv, classpaths, mainClass))
  {
    std::cerr << "Usage: " << argv[0] << " [-cp <path>] <MainClass>" << std::endl;
    return 1;
  }

  // 输出结果
  std::cout << "Main class: " << mainClass << std::endl;
  // std::cout << "Classpath (absolute):" << std::endl;
  std::string cp = joinClasspath(classpaths);
  std::cout << "Classpath string: " << cp << std::endl;

  startVM();
  cp.append("/").append(mainClass).append(".class");
  std::cout << "Class file path string: " << cp << std::endl;

  JavaThread *javaThread = new JavaThread; // 模拟线程的创建
  Threads::curThread = javaThread;
  InstanceKlass *klass = BootClassLoader::loadKlass(cp);                                 // 加载HelloJVM类
  MethodInfo *m = JavaNativeInterface::getMethod(klass, "main", "([Ljava/lang/String;)V"); // 遍历klass所有的方法，找到main方法
  JavaNativeInterface::callStaticMethod(javaThread, m);                                    // 执行main方法
  return 0;
}

void startVM()
{
  CodeRunBase::initCodeRun();   // 初始化字节码解释器，把解析JVM指令的方法全部存入map,以便使用
  CodeRunNative::initCodeRun(); // 初始化本地方法，把本地方法全部存入map,以便使用
}

// 解析命令行参数
bool parseArgs(int argc, char *argv[],
               std::vector<std::filesystem::path> &classpaths,
               std::string &mainClassName)
{
  classpaths.clear();
  mainClassName.clear();

  for (int i = 1; i < argc; ++i)
  {
    std::string arg = argv[i];

    if (arg == "-cp" || arg == "-classpath")
    {
      if (i + 1 >= argc)
      {
        std::cerr << "Error: missing argument for " << arg << std::endl;
        return false;
      }
      std::string cp = argv[++i];

      // 拆分 classpath（Linux/macOS 用 ':'，Windows 用 ';'）
#ifdef _WIN32
      char delimiter = ';';
#else
      char delimiter = ':';
#endif

      size_t start = 0;
      size_t end = cp.find(delimiter);
      while (true)
      {
        std::string pathStr = (end == std::string::npos)
                                  ? cp.substr(start)
                                  : cp.substr(start, end - start);

        if (!pathStr.empty())
        {
          std::filesystem::path p(pathStr);
          // 转为绝对路径
          try
          {
            if (p.is_relative())
            {
              p = std::filesystem::absolute(p);
            }
            // 规范化路径（可选）
            p = std::filesystem::canonical(p); // 会检查路径是否存在，若不想检查可用 weakly_canonical
          }
          catch (const std::filesystem::filesystem_error &e)
          {
            std::cerr << "Warning: classpath entry not found: " << p << std::endl;
            // 可选择跳过或保留原路径
          }
          classpaths.push_back(p);
        }

        if (end == std::string::npos)
          break;
        start = end + 1;
        end = cp.find(delimiter, start);
      }
    }
    else if (!mainClassName.empty())
    {
      std::cerr << "Error: multiple main classes specified: " << mainClassName << " and " << arg << std::endl;
      return false;
    }
    else if (arg[0] != '-')
    {
      // 假设第一个非选项参数是主类名
      mainClassName = arg;
    }
    else
    {
      std::cerr << "Error: unknown option: " << arg << std::endl;
      return false;
    }
  }

  if (mainClassName.empty())
  {
    std::cerr << "Error: no main class specified" << std::endl;
    return false;
  }

  if (classpaths.empty())
  {
    // 默认 classpath 为当前目录
    classpaths.push_back(std::filesystem::current_path());
  }

  return true;
}

std::string joinClasspath(const std::vector<std::filesystem::path> &classpaths)
{
  if (classpaths.empty())
    return "";

#ifdef _WIN32
  const char sep = ';';
#else
  const char sep = ':';
#endif

  std::string result;
  for (size_t i = 0; i < classpaths.size(); ++i)
  {
    if (i > 0)
      result += sep;
    result += classpaths[i].generic_string(); // 使用 / 分隔，更干净
  }
  return result;
}
